<?php

class Adb_Field extends Adb
{

  /**
   *
   * @var AdbTable
   */
  protected $table;

  /**
   *
   * @var string
   */
  protected $type;

  /**
   *
   * @var integer
   */
  protected $length;

  /**
   *
   * @var boolean
   */
  protected $unsigned;

  /**
   *
   * @var boolean
   */
  protected $notNull;

  /**
   *
   * @var boolean
   */
  protected $fixed = true;

  /**
   *
   * @var mixed
   */
  protected $default;

  public function __construct(AdbTable $table, $name)
  {
    parent::__construct($name);

    $this->table = $table;

    $this->loadDefinition();
  }

  protected function loadDefinition()
  {
    if ($this->exists()) {
      $definition = $this->getDefinition();
      
      $this->type = sy_get_param($definition, 'type');
      $this->length = sy_get_param($definition, 'length');
      $this->unsigned = sy_get_param($definition, 'unsigned');
      $this->notNull = sy_get_param($definition, 'notnull');
      $this->default = sy_get_param($definition, 'default');
    }
  }

  /**
   * 
   * @return array
   */
  protected function buildDefinition()
  {
    $definition = array();

    $definition['type'] = $this->getType();
    $definition['length'] = $this->getLength();
    $definition['unsigned'] = $this->getUnsigned();
    $definition['notnull'] = $this->getNotNull();
    $definition['default'] = $this->getDefault();

    //array_filter($definition);

    return $definition;
  }

  /**
   * 
   * @return boolean
   */
  public function exists()
  {
    $fields = $this->manager()->listTableFields($this->table->getName());
    return in_array($this->getName(), $fields);
  }

  /**
   * 
   * @return array
   */
  public function getDefinition()
  {
    $definition = $this->reverse()->getTableFieldDefinition($this->table->getName(), $this->getName());
    return $definition[0];
  }

  /**
   * 
   * @return AdbField
   */
  public function create()
  {
    if ($this->exists()) {
      $definition = $this->getDefinition();

      $diff = array_diff($this->buildDefinition(), $definition);

      $diff['definition'] = array_merge($definition, $diff);

      $changes = array('change' => array($this->getName() => $diff));
    }
    else {
      $definition = $this->buildDefinition();
      
      $changes = array('add' => array($this->getName() => $definition));
    }

    $result = $this->manager()->alterTable($this->table->getName(), $changes, false);

    MDB2_DAO::validate($result);

    return $this;
  }

  /**
   *
   * TODO: can´t rename primary key
   * 
   * @return AdbField
   */
  public function rename($name)
  {
    $definition = $this->getDefinition();

    $changes = array('rename' => array($this->getName() => array('name' => $name, 'definition' => $definition)));

    $result = $this->manager()->alterTable($this->table->getName(), $changes, false);

    MDB2_DAO::validate($result);

    $this->name = $name;

    return $this;
  }

  /**
   * 
   * @return AdbField
   */
  public function remove()
  {
    $changes = array('remove' => array($this->getName() => array()));

    $result = $this->manager()->alterTable($this->table->getName(), $changes, false);

    MDB2_DAO::validate($result);

    return $this;
  }

  public function getType()
  {
    if (empty($this->type)) {
      throw new Exception("Field {$this->getName()} has no type declaration");
    }

    return $this->type;
  }

  public function getLength()
  {
    return $this->length;
  }

  public function getUnsigned()
  {
    return $this->unsigned;
  }

  public function getNotNull()
  {
    return $this->notNull;
  }

  public function getDefault()
  {
    return $this->default;
  }

  public function getFixed()
  {
    return $this->fixed;
  }

  /**
   * 
   * @return AdbField
   */
  public function setType($value)
  {
    $this->type = $value;
    return $this;
  }

  /**
   * 
   * @return AdbField
   */
  public function setLength($value)
  {
    $this->length = $value;
    return $this;
  }

  /**
   * 
   * @return AdbField
   */
  public function setUnsigned($value)
  {
    $this->unsigned = $value;
    return $this;
  }

  /**
   * 
   * @return AdbField
   */
  public function setNotNull($value)
  {
    $this->notNull = $value;
    return $this;
  }

  /**
   * 
   * @return AdbField
   */
  public function setDefault($value)
  {
    $this->default = $value;
    return $this;
  }

  /**
   * 
   * @return AdbField
   */
  public function setFixed($value)
  {
    $this->fixed = $value;
    return $this;
  }

}
